package birdsong.server;


import java.util.ArrayList;
import java.util.LinkedList;


import birdsong.comm.ServerComm;
import birdsong.comm.ServerSideMessage;
import birdsong.server.BirdsongServer;

/**
 * The server that:  keep track of who follows who and forward Birdsong messages accordingly; 
 * keep clients informed about who follows and unfollows them;
 * when a new client connects, the server send the list of currently connected user to that client so that the client will have an updated list of all currently connected users;
 * when a client connects or disconnects, the server sends a message with the appropriate
information to all connected clients
 * @author Pedro
 *
 */



public class Server implements BirdsongServer {


	ArrayList<User> listOfUsers = new ArrayList<User>();

	@Override
	public void start(ServerComm serverTester) {

		serverTester.start();


		while (true) {


			if (serverTester.hasNextMessage()){

				ServerSideMessage message = serverTester.getNextMessage();

				//checks if the message is type BIRDSONG_MESSAGE
				if (message.getType() == ServerSideMessage.Type.BIRDSONG_MESSAGE) {


					LinkedList<String> tempFollowers = new LinkedList<String>();

					//return the list of Seguidores
					for (User a: listOfUsers){
						if (a.toString().equals(message.getClientNickname())){
							tempFollowers = a.getSeguidores();
						}
					}

					//sends to all of his followers the message
					for (String t : tempFollowers){
						serverTester.sendBirdsongMessage(message.getClientNickname(), t.toString(), message.getPayload());
					}
				}

				//checks if the message is type CLIENT_CONECTED
				else if (message.getType() == ServerSideMessage.Type.CLIENT_CONNECTED){

					boolean tempIsRegisteredUser = false;

					// Verifies if is registered user and if is, set him connected 
					for (User a: listOfUsers){
						if (a.getUser() == message.getClientNickname()){
							tempIsRegisteredUser = true;
							a.setConnected();

						}

					}


					//If not registered, create a new User and sets Connected
					if (tempIsRegisteredUser == false){

						listOfUsers.add(new User(message.getClientNickname()));
						System.out.println("SERVER -->Just created a new User " + message.getClientNickname());

						for (User u:listOfUsers){
							if (u.getUser() == message.getClientNickname())
								u.setConnected();
						}
					}


					//	Sends an sendClientConnected to all user that are connected to the servers

					for (User u: listOfUsers){
						if (u.isConnected() && u.getUser() != message.getClientNickname())
							serverTester.sendClientConnected(message.getClientNickname(), u.getUser());
					}	
				}


				//checks if the message is type CLIENT_DISCONNECTED
				else if (message.getType() == ServerSideMessage.Type.CLIENT_DISCONNECTED){


					LinkedList<String> tempEstaASeguir = new LinkedList<String>();

					//sends to all users that are connected an message sendClientDisconnected

					for (User u: listOfUsers){
						if (u.isConnected() && u.getUser() != message.getClientNickname())
							serverTester.sendClientDisconnected(u.getUser(),message.getClientNickname()); 
					}	

					//sets the user as disconnected and removes all of his followers
					for (User a:listOfUsers){
						if (a.getUser() == message.getClientNickname()){
							a.setDisconnect();

							System.out.println(" SERVER-->The user " + message.getClientNickname() + " is disconnecting");
							a.removeAllSeguidores();


							if (!a.isListASeguirEmpty()){
								tempEstaASeguir = a.getEstaASeguir();

								for (int i = 0; i !=tempEstaASeguir.size(); i++){
									serverTester.sendNewUnfollow(tempEstaASeguir.get(i), message.getClientNickname());
								}	
							}
						}	
					}
				}

				//checks if the message is type FOLLOW
				else if (message.getType() == ServerSideMessage.Type.FOLLOW){

					for (User a: listOfUsers){
						if (a.getUser() == message.getClientNickname()){

							//If not in his list of Following, it add him to the list and sends a sendNewFollowers message.
							if (!a.inTheListASeguir(message.getPayload())){ 
								a.addEstaASeguir(message.getPayload());
								serverTester.sendNewFollower(message.getClientNickname(), message.getPayload());
							}
							else
								//if in the list, it sends one error message
								serverTester.sendError(message.getClientNickname(), " Already following the requested user");

						}
						else if (a.getUser() == message.getPayload()){
							a.addSeguidor(message.getClientNickname());
						}
					}
				}

				//checks if the message is type UNFOLLOW
				else if (message.getType() == ServerSideMessage.Type.UNFOLLOW){


					for (User a: listOfUsers){
						if (a.getUser() == message.getClientNickname()){

							//If is in the list of users he his following, it removes and sends a message sendNewUnfollow
							if(a.inTheListASeguir(message.getPayload())){
								a.removeEstaASeguir(message.getPayload());

								serverTester.sendNewUnfollow(message.getPayload(),message.getClientNickname());

							}
							else
								//Of not in the list, sends one error message
								serverTester.sendError(message.getClientNickname(), " Not following the requested user");
						}
						//removes the user from followers
						else if (a.getUser() == message.getPayload()){
							a.removeSeguidor(message.getClientNickname());
						}
					}

				}

				else {
					//If it sends one message that has no Type than the others, it sends one erros message
					serverTester.sendError(message.getClientNickname(), "Erro - serviço solicitado não existente!!!!");
				}
			}

		}

	}
}

